package main

import (
	"encoding/json"
	"fmt"
	"httpserver"
	"io/ioutil"
	"net/http"
	"os"
	"path/filepath"
	"strings"
	"time"
	"utils"

	ffmt "gopkg.in/ffmt.v1"
)

const DirName string = "ControlUserInfo/"
const FileType string = ".json"

type controlUserInfo struct {
	GameID     uint32
	Range      int32
	Rate       int32
	Score      int32
	CreateTime string
	UpdateTime string
}

func NewControlUserInfoToJson(gameid uint32, rangeScore, rate, NowScore int32, CreateTime, UpdateTime string) []byte {

	p := &controlUserInfo{}
	p.GameID = gameid
	p.Rate = rangeScore
	p.Range = rate
	p.Score = NowScore

	p.CreateTime = CreateTime
	p.UpdateTime = UpdateTime //time.Now().Format("2006-01-02 15:04:05")

	data, _ := json.Marshal(p)
	fmt.Println(string(data))
	return data
}

type controlErroDesc struct {
	ErrorCode int
	ErrorStr  string
	Page      int
	Size      int
	Total     int
	Data      []*controlUserInfo
}

func NewControlErrorDesc(id int, desc string, Descdata []*controlUserInfo, page, size, total int) []byte {

	p := &controlErroDesc{}
	p.ErrorCode = id
	p.ErrorStr = desc
	p.Page = page
	p.Size = size
	p.Total = total
	p.Data = Descdata
	data, _ := json.Marshal(p)
	return (data)
}

//读取操作
func IndexHandler_Read(w http.ResponseWriter, r *http.Request) {

	fmt.Println("进入读取操作")
	//ffmt.P(r)

	r.ParseForm()

	//文件名称
	name := DirName + r.Form["GameID"][0] + FileType

	if contents, err := ioutil.ReadFile(name); err == nil {
		//因为contents是[]byte类型，直接转换成 string类型后会多一行空格,需要使用strings.Replace替换换行符
		result := strings.Replace(string(contents), "\n", "", 1)
		p := &controlUserInfo{}
		json.Unmarshal([]byte(result), p)
		sliceControlUserInfo := make([]*controlUserInfo, 0)
		sliceControlUserInfo = append(sliceControlUserInfo, p)
		w.Write(NewControlErrorDesc(0, "SUCCESS", sliceControlUserInfo, 0, 0, 0))
	} else {
		//回复页面
		w.Write(NewControlErrorDesc(3, "GameID不存在", nil, 0, 0, 0))
	}
}

//写入操作
func IndexHandler_Write(w http.ResponseWriter, r *http.Request) {

	fmt.Println("进入写入操作")
	//	ffmt.P(r)

	r.ParseForm()

	//文件名称
	name := DirName + r.Form["GameID"][0] + FileType

	var data []byte
	if contents, err := ioutil.ReadFile(name); err == nil {

		p := &controlUserInfo{}
		json.Unmarshal([]byte(contents), p)

		//构造结构
		data = NewControlUserInfoToJson(
			utils.S2i32_U(r.Form["GameID"][0]),
			utils.S2i32(r.Form["Rate"][0]),
			utils.S2i32(r.Form["Range"][0]),
			0,
			p.CreateTime,
			time.Now().Format("2006-01-02 15:04:05"),
		)
	} else {
		//构造结构
		data = NewControlUserInfoToJson(
			utils.S2i32_U(r.Form["GameID"][0]),
			utils.S2i32(r.Form["Rate"][0]),
			utils.S2i32(r.Form["Range"][0]),
			0,
			time.Now().Format("2006-01-02 15:04:05"),
			time.Now().Format("2006-01-02 15:04:05"),
		)
	}

	content := data
	WriteWithIoutil(name, content)

	//回复页面
	w.Write(NewControlErrorDesc(0, "Success", nil, 0, 0, 0))
}

//删除操作
func IndexHandler_Delete(w http.ResponseWriter, r *http.Request) {

	fmt.Println("进入删除操作")
	//ffmt.P(r)
	r.ParseForm()

	//文件名称
	name := DirName + r.Form["GameID"][0] + FileType
	fmt.Println(name)

	isSuccess, _ := DelteFile(name)
	if isSuccess {
		w.Write(NewControlErrorDesc(0, "Success", nil, 0, 0, 0))
	} else {
		w.Write(NewControlErrorDesc(1, "error", nil, 0, 0, 0))
	}

	getFilelist(DirName)
}

//全部删除
func IndexHandler_DeleteALL(w http.ResponseWriter, r *http.Request) {

	fmt.Println("进入全部删除操作")
	r.ParseForm()

	sliceFileName := make([]string, 0)

	err := filepath.Walk(DirName,
		func(path string, f os.FileInfo, err error) error {
			if f == nil {
				return err
			}
			if f.IsDir() {
				return nil
			}

			sliceFileName = append(sliceFileName, path)
			return nil
		})
	if err != nil {
		fmt.Printf("filepath.Walk() returned %v\n", err)
	}

	fmt.Println("检索文件数量:", len(sliceFileName))

	var delSuccess = true
	for i, v := range sliceFileName {
		fmt.Println(i, v)
		ret, err := DelteFile(v)
		fmt.Println(ret, err)
		if ret == false {
			 delSuccess = false
			 break
		}
	}

	if delSuccess{
		w.Write(NewControlErrorDesc(0, "Success", nil, 0, 0, 0))
	}else{
		w.Write(NewControlErrorDesc(1, "error", nil, 0, 0, 0))
	}
}

//分页
func IndexHandler_Page(w http.ResponseWriter, r *http.Request) {

	fmt.Println("进入分页操作")
	//ffmt.P(r)

	r.ParseForm()

	page := utils.S2i(r.Form["page"][0])
	size := utils.S2i(r.Form["size"][0])
	fmt.Println(page, size)

	//遍历文件夹
	sliceFileName := getFilelist(DirName)
	fmt.Println(len(sliceFileName))

	//计算分页
	var minindex = int((page - 1) * size)
	var maxindex = page * size

	fmt.Println(fmt.Sprintf("minindex:%d maxindex:%d", minindex, maxindex))

	var maxListlegth = len(sliceFileName)
	fmt.Println("列表最大值", maxListlegth)

	//防止过界
	if maxindex > maxListlegth {
		maxindex = maxListlegth
	}

	//安全范围
	if minindex >= 0 && maxindex <= maxListlegth {

		checkList := sliceFileName[minindex:maxindex]
		sliceControlUserInfo := make([]*controlUserInfo, 0)
		for _, name := range checkList {
			//fmt.Println(fmt.Sprintf("i:%d name:%s", i, name))
			isSuccess, p := ReadFile(name)
			if isSuccess {
				sliceControlUserInfo = append(sliceControlUserInfo, p)
			}
		}
		w.Write(NewControlErrorDesc(0, "success", sliceControlUserInfo, page, size, maxListlegth))
	} else {
		w.Write(NewControlErrorDesc(1, "error", nil, 0, 0, 0))
	}
}

//分页
func IndexHandler_VerSion(w http.ResponseWriter, r *http.Request) {

	fmt.Println("修改服务器版本")
	//ffmt.P(r)

	r.ParseForm()

	verSion := utils.S2i32_U(r.Form["NewVer"][0])
	fmt.Println(verSion)
	dwChannel := utils.S2i32_U(r.Form["Channel"][0])
	fmt.Println(dwChannel)

	//创建链接
	ch := make(chan int)
	cliletScoket := httpserver.MakeNewWsToTcp(ch)

	if cliletScoket.ConnentFoxServer("127.0.0.1:8640") == false {
		cliletScoket.Close()
	} else {
		CmdWriteVerSion := new(utils.CMD_WriteVerSion)
		CmdWriteVerSion.DwVersion = verSion
		CmdWriteVerSion.DWChannel = dwChannel
		cliletScoket.SendData(utils.MDM_GP_GMSERVER, utils.SUB_GP_WRITEVERSION, CmdWriteVerSion)
	}

	timeout := time.After(5 * time.Second)

	select {
	case x := <-ch:
		close(ch)
		if x == 0 {
			w.Write(NewControlErrorDesc(1, "success", nil, 0, 0, 0))
		} else {
			w.Write(NewControlErrorDesc(1, "error", nil, 0, 0, 0))
		}
		break
	case <-timeout:
		close(ch)
		w.Write(NewControlErrorDesc(1, "timeout", nil, 0, 0, 0))
		fmt.Println("timeout..")
		break
	}

	//关闭网络
	cliletScoket.Close()
}

//读取单个文件
func ReadFile(name string) (bool, *controlUserInfo) {

	if contents, err := ioutil.ReadFile(name); err == nil {
		//因为contents是[]byte类型，直接转换成 string类型后会多一行空格,需要使用strings.Replace替换换行符
		result := strings.Replace(string(contents), "\n", "", 1)
		p := &controlUserInfo{}
		json.Unmarshal([]byte(result), p)
		return true, p
	}
	return false, nil
}

//删除文件
func DelteFile(name string) (bool, error) {
	del := os.Remove(name)
	if del != nil {
		fmt.Println(del)
		return false, del
	}
	return true, del
}

//写入文件
func WriteWithIoutil(name string, content []byte) {

	if ioutil.WriteFile(name, content, 0644) == nil {
		fmt.Println("写入文件成功:", name)
	}
}

//遍历文件夹
func getFilelist(path string) []string {

	sliceFileName := make([]string, 0)

	//	files, _ := filepath.Glob("ControlUserInfo/*.json")
	//	fmt.Println(files)

	err := filepath.Walk(path,
		func(path string, f os.FileInfo, err error) error {
			if f == nil {
				return err
			}
			if f.IsDir() {
				return nil
			}

			if checkUserControlOld(path) == false {
				return nil
			}

			//println(path)
			sliceFileName = append(sliceFileName, path)
			return nil
		})
	if err != nil {
		fmt.Printf("filepath.Walk() returned %v\n", err)
	}

	return sliceFileName
}

func checkUserControlOld(path string) bool {

	//检测过期
	isOpen, p := ReadFile(path)

	if isOpen {
		if p.Range > 0 {
			if p.Score > p.Range {
				fmt.Println(fmt.Sprintf("满足正值条件 准备删除"))
				ffmt.P(p)
				DelteFile(path)
				return false
			}
		} else {
			if p.Score < p.Range {
				fmt.Println(fmt.Sprintf("满足负值条件 准备删除"))
				ffmt.P(p)
				DelteFile(path)
				return false
			}
		}
	}

	return true
}

func main() {

	//IndexHandler_DeleteALL(nil, nil)

	http.HandleFunc("/control/Read", IndexHandler_Read)
	http.HandleFunc("/control/Save", IndexHandler_Write)
	http.HandleFunc("/control/Delete", IndexHandler_Delete)
	http.HandleFunc("/control/Page", IndexHandler_Page)
	http.HandleFunc("/control/DeleteALL", IndexHandler_DeleteALL)
	http.HandleFunc("/OnUpdateHallVersion.html", IndexHandler_VerSion)

	fmt.Println("服务启动成功:")
	http.ListenAndServe(":18000", nil)
}
